package org.pentaho.di.trans.steps.abnormalcheck;

import org.apache.commons.lang3.StringUtils;
import org.pentaho.di.core.CheckResult;
import org.pentaho.di.core.CheckResultInterface;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.exception.KettleXMLException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.row.value.ValueMetaString;
import org.pentaho.di.core.variables.VariableSpace;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.*;
import org.pentaho.di.trans.steps.univariatestats.UnivariateStats;
import org.pentaho.di.trans.steps.univariatestats.UnivariateStatsData;
import org.pentaho.di.trans.steps.univariatestats.UnivariateStatsMetaFunction;
import org.pentaho.metastore.api.IMetaStore;
import org.w3c.dom.Node;

import java.util.Arrays;
import java.util.List;

/**
 * @author dc
 * @Type AbnormalCheckMeta.java
 * @Desc
 * @date 2022/10/19 10:23
 */
public class AbnormalCheckMeta extends BaseStepMeta implements StepMetaInterface {

    private AbnormalCheckConfig[] configs;


    @Override
    public void loadXML(Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore) throws KettleXMLException {
        int nrStats = XMLHandler.countNodes(stepnode, AbnormalCheckConfig.XML_TAG);
        allocate(nrStats);
        for (int i = 0; i < nrStats; i++) {
            Node checkNode = XMLHandler.getSubNodeByNr(stepnode, AbnormalCheckConfig.XML_TAG, i);
            configs[i] = new AbnormalCheckConfig(checkNode);
        }
    }

    public void allocate(int nrStats) {
        configs = new AbnormalCheckConfig[nrStats];
    }

    @Override
    public String getXML() {
        StringBuilder retval = new StringBuilder(300);
        if (configs != null) {
            for (int i = 0; i < configs.length; i++) {
                retval.append("       ").append(configs[i].getXML()).append(Const.CR);
            }
        }
        return retval.toString();
    }

    /**
     * Check for equality
     *
     * @param obj an <code>Object</code> to compare with
     * @return true if equal to the supplied object
     */
    @Override
    public boolean equals(Object obj) {
        if (obj != null && (obj.getClass().equals(this.getClass()))) {
            AbnormalCheckMeta m = (AbnormalCheckMeta) obj;
            return (getXML().equals(m.getXML()));
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(configs);
    }

    /**
     * Clone this step's meta data
     *
     * @return the cloned meta data
     */
    @Override
    public Object clone() {
        AbnormalCheckMeta retval = (AbnormalCheckMeta) super.clone();
        if (configs != null) {
            retval.allocate(configs.length);
            for (int i = 0; i < configs.length; i++) {
                retval.getConfigs()[i] = (AbnormalCheckConfig) configs[i].clone();
            }
        } else {
            retval.allocate(0);
        }
        return retval;
    }

    /**
     * Set the default state of the meta data?
     */
    @Override
    public void setDefault() {
        configs = new AbnormalCheckConfig[0];
    }

    @Override
    public void readRep(Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases)
            throws KettleException {

        int nrStats = rep.countNrStepAttributes(id_step, "source_field_name");
        allocate(nrStats);

        for (int i = 0; i < nrStats; i++) {
            configs[i] = new AbnormalCheckConfig(rep, id_step, i);
        }
    }

    @Override
    public void saveRep(Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step)
            throws KettleException {

        for (int i = 0; i < configs.length; i++) {
            configs[i].saveRep(rep, metaStore, id_transformation, id_step, i);
        }
    }

    /**
     * 配置流向下一个节点的字段
     * @param outPutRowMeta
     * @param origin
     * @param info
     * @param nextStep
     * @param space
     * @param repository
     * @param metaStore
     * @throws KettleStepException
     */
    @Override
    public void getFields(RowMetaInterface outPutRowMeta, String origin, RowMetaInterface[] info, StepMeta nextStep,
                          VariableSpace space, Repository repository, IMetaStore metaStore) throws KettleStepException {
        if(configs!=null&&configs.length>0){
            String judgeName = configs[0].getJudgeName();
            if (StringUtils.isNotEmpty(judgeName)) {
                ValueMetaInterface v = new ValueMetaString( space.environmentSubstitute( judgeName ) );
                v.setOrigin( origin );
                outPutRowMeta.addValueMeta( v );
            }
        }
    }


    @Override
    public void check(List<CheckResultInterface> remarks, TransMeta transmeta, StepMeta stepMeta, RowMetaInterface prev,
                      String[] input, String[] output, RowMetaInterface info, VariableSpace space, Repository repository,
                      IMetaStore metaStore) {

        CheckResult cr;

        if ((prev == null) || (prev.size() == 0)) {
            cr = new CheckResult(CheckResult.TYPE_RESULT_WARNING, "Not receiving any fields from previous steps!", stepMeta);
            remarks.add(cr);
        } else {
            cr =
                    new CheckResult(CheckResult.TYPE_RESULT_OK, "Step is connected to previous one, receiving " + prev.size()
                            + " fields", stepMeta);
            remarks.add(cr);
        }

        // See if we have input streams leading to this step!
        if (input.length > 0) {
            cr = new CheckResult(CheckResult.TYPE_RESULT_OK, "Step is receiving info from other steps.", stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, "No input received from other steps!", stepMeta);
            remarks.add(cr);
        }
    }

    @Override
    public StepInterface getStep(StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta tr,
                                 Trans trans) {
        return new AbnormalCheck(stepMeta, stepDataInterface, cnr, tr, trans);
    }

    @Override
    public StepDataInterface getStepData() {
        return new AbnormalCheckData();
    }

    public AbnormalCheckConfig[] getConfigs() {
        return configs;
    }

    public void setConfigs(AbnormalCheckConfig[] configs) {
        this.configs = configs;
    }

    public int getNumFieldsToProcess() {
        int tem=0;
        if(configs!=null&&configs.length>0){
           tem=configs.length;
        }
        return tem;
    }
}
    
